home *** CD-ROM | disk | FTP | other *** search
-
- #include <Icons.h>
- #include <Aliases.h>
- #include <AERegistry.h>
- #include <Gestalt.h>
- #include <AEPackObject.h>
- #include <AEObjects.h>
- #include <Errors.h>
- #include <TextUtils.h>
-
- #define DEBUGLEVEL DEBUGFULL
- #include "Exceptions.h"
- #include "FinderStuff.h"
-
-
- AEDesc pFinderTarget;
-
-
-
- Size GetSizeFromIconType(OSType iconType);
-
-
- //----------------------------------------------------------------------------
- // FailOSErr
- //----------------------------------------------------------------------------
- void FailOSErr(OSErr err)
- {
- if (err != noErr) {
- Str255 str;
-
- NumToString(err, str);
- DebugStr(str);
- }
- }
-
-
- //----------------------------------------------------------------------------
- // InitFinderAE
- //----------------------------------------------------------------------------
- OSErr InitFinderAE()
- {
- OSErr err;
- DescType finderSig = 'MACS';
-
- err = AECreateDesc(typeApplSignature, (Ptr) &finderSig,
- sizeof(DescType), &pFinderTarget);
-
- check(err == noErr);
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // BuildHFSDescList
- //----------------------------------------------------------------------------
- OSErr BuildHFSDescList(DragReference theDrag, AEDescList *hfsList)
- {
- ItemReference itemRef;
- Size dataSize;
- FSSpec theFile;
- OSErr err;
- unsigned short numItems, counter;
-
- err = AECreateList(NULL, 0, false, hfsList);
-
- CountDragItems(theDrag, &numItems);
-
- for (counter = 1; counter <= numItems; counter++) {
- err = GetDragItemReferenceNumber(theDrag, counter, &itemRef);
-
- dataSize = sizeof(FSSpec);
- err = GetFlavorData(theDrag, kRealSpecItemRef, flavorTypeRealSpec,
- &theFile, &dataSize, 0);
-
- if (err == noErr) {
- //
- // This is an hfs flavor object, put it in the file list.
- //
- err = AddSpecToDescList(hfsList, &theFile);
- }
- }
-
- check(err == noErr);
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // HandleDragCloneMove
- //
- // Walk the drag items and collect the items in it. Then move them to
- // the location pointed to by the full pathname (only for now, of course).
- //----------------------------------------------------------------------------
- OSErr HandleDragCloneMove(DragReference theDrag)
- {
- AEDescList fileDescList;
- OSErr err;
- FSSpec descSpec;
- Point globalPt;
- short modifiers;
- Boolean moveIt;
-
- moveIt = true;
- err = paramErr;
- require(HaveScriptableFinder(), ScriptableFinderDead);
-
- err = BuildHFSDescList(theDrag, &fileDescList);
- require(err == noErr, BuildHFSDescList);
-
- err = GetDropFSSpec(theDrag, &descSpec);
- require(err == noErr, GetDropFSSpec);
-
- err = GetDragModifiers(theDrag, &modifiers, NULL, NULL);
- check(err == noErr);
- if (err == noErr)
- moveIt = !(modifiers & optionKey);
-
- (void) GetDragMouse(theDrag, &globalPt, NULL);
- err = CloneMoveDescList(&fileDescList, &descSpec, globalPt, false, moveIt);
-
- GetDropFSSpec:
- BuildHFSDescList:
- ScriptableFinderDead:
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // FinderIsRunning
- //
- // Walk the Process Mgr list to check if the Finder is running
- //----------------------------------------------------------------------------
- Boolean FinderIsRunning()
- {
- OSErr err;
- ProcessInfoRec pInfo;
- ProcessSerialNumber psn;
- Boolean foundIt;
-
- foundIt = false;
- psn.highLongOfPSN = 0; psn.lowLongOfPSN = kNoProcess;
-
- while ((foundIt == false) && (GetNextProcess(&psn) == noErr)) {
- pInfo.processName = NULL;
- pInfo.processAppSpec = NULL;
- pInfo.processInfoLength = sizeof(ProcessInfoRec);
-
- err = GetProcessInformation(&psn, &pInfo);
-
- if ((err == noErr)
- && (pInfo.processSignature == 'MACS')
- && (pInfo.processType == 'FNDR'))
-
- foundIt = true;
- }
-
- return foundIt;
- }
-
-
- //----------------------------------------------------------------------------
- // HaveScriptableFinder
- //
- // We have it if the Gestalt bit is set and the Finder is running
- //----------------------------------------------------------------------------
- Boolean HaveScriptableFinder()
- {
- long response;
- Boolean haveScriptableFinder;
- OSErr err;
-
- haveScriptableFinder = false;
-
- err = Gestalt(gestaltFinderAttr, &response);
- require(err == noErr, Gestalt);
-
- if ((response & (1 << gestaltOSLCompliantFinder)) && (FinderIsRunning()))
- haveScriptableFinder = true;
-
- Gestalt:
- return haveScriptableFinder;
- }
-
-
- //----------------------------------------------------------------------------
- // SendAppleEvent
- //----------------------------------------------------------------------------
- OSErr SendAppleEvent(AppleEvent *ae, AppleEvent *reply, AESendMode sendMode)
- {
- AppleEvent throwAwayReply;
- OSErr err;
-
- if (reply == NULL) {
- err = AESend(ae, &throwAwayReply, sendMode,
- kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
- if (err == noErr)
- AEDisposeDesc(&throwAwayReply);
- }
- else
- err = AESend(ae, reply, sendMode,
- kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
-
- check(err == noErr);
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // MakeAppleEvent
- //----------------------------------------------------------------------------
- OSErr MakeAppleEvent(AEEventClass aeClass, AEEventID aeID,
- AEDesc *target, AppleEvent *ae)
- {
- OSErr err;
-
- err = AECreateAppleEvent(aeClass, aeID, target,
- kAutoGenerateReturnID, kAnyTransactionID, ae);
-
- check(err == noErr);
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // AddSpecToDescList
- //
- // Pass this a created descriptor list.
- //----------------------------------------------------------------------------
- OSErr AddSpecToDescList(AEDescList *descList, FSSpecPtr theSpec)
- {
- OSErr err;
- AEDesc fileDesc;
- AliasHandle fileAlias;
-
- // Init the desc handles
- fileAlias = NULL;
- fileDesc.dataHandle = NULL;
-
- err = NewAlias(NULL, theSpec, &fileAlias);
- require(err == noErr, NewAlias);
-
- HLock((Handle) fileAlias);
- err = AECreateDesc(typeAlias, (Ptr) *fileAlias,
- GetHandleSize((Handle) fileAlias), &fileDesc);
- HUnlock((Handle) fileAlias);
- require(err == noErr, AECreateDesc);
-
- err = AEPutDesc(descList, 0, &fileDesc);
-
- AECreateDesc:
- NewAlias:
- if (fileDesc.dataHandle != NULL) (void) AEDisposeDesc(&fileDesc);
- if (fileAlias != NULL) DisposeHandle((Handle) fileAlias);
-
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // MakeSpecifierForSelection
- //----------------------------------------------------------------------------
-
- OSErr MakeSpecifierForSelection(AEDesc *selectionSpecifier)
- {
- OSErr err;
- DescType descData;
- AEDesc keyData, nullDescriptor;
-
- nullDescriptor.descriptorType = typeNull;
- nullDescriptor.dataHandle = NULL;
-
- //
- // Make a descriptor whose type is 'typeType' and whose
- // contents are 'pSelection' (defined in FinderRegistry.h).
- // This descriptor specifies the property of the null container
- // that we are interested in--in this case, the selection.
- //
- descData = pSelection;
- err = AECreateDesc(typeType, (Ptr) &descData, sizeof(DescType), &keyData);
- require(err == noErr, AECreateDesc);
-
- err = CreateObjSpecifier(cProperty, &nullDescriptor, formPropertyID,
- &keyData, true, selectionSpecifier);
-
- AECreateDesc:
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // GetIconSuiteFromFinder
- //
- // Send a GetData AE for the 'ifam'
- //----------------------------------------------------------------------------
- OSErr GetIconSuiteFromFinder(FSSpecPtr hfsObj, Handle *iconSuite)
- {
- OSErr err;
- AppleEvent finderEvent, replyEvent;
- AEDesc fileSpecifier, iconPropertySpecifier;
- DescType returnType;
- Size returnSize;
- long returnLong;
- AEDesc iconFamily;
-
- //
- // Set up our locals for easy cleanup
- //
- *iconSuite = NULL;
-
- //
- // Make sure the Finder is scriptable and is running.
- //
- err = paramErr;
- require(HaveScriptableFinder() == true, HaveScriptableFinder);
-
- //
- // Make a GetData Apple event to send to the Finder
- //
- err = MakeAppleEvent(kAECoreSuite, kAEGetData, &pFinderTarget,
- &finderEvent);
- require(err == noErr, MakeAppleEvent);
-
- //
- // Make an object specifier for the interesting file
- //
- err = MakeSpecifierForFile(hfsObj, &fileSpecifier);
- require(err == noErr, MakeSpecifierForFile);
-
- //
- // Make an icon family property specifier for the file
- //
- err = MakePropertySpecifierForSpecifier(pIconBitmap, &fileSpecifier,
- &iconPropertySpecifier);
- require(err == noErr, MakePropertySpecifierForSpecifier);
-
- //
- // Stuff it in the Apple event and send it
- //
- err = AEPutParamDesc(&finderEvent, keyDirectObject, &iconPropertySpecifier);
- require(err == noErr, AEPutParamDesc);
-
- err = SendAppleEvent(&finderEvent, &replyEvent,
- kAEWaitReply + kAECanInteract + kAECanSwitchLayer);
- require(err == noErr, SendAppleEvent);
-
- //
- // Now the Finder may have sent us an error number
- //
- err = AEGetParamPtr(&replyEvent, keyErrorNumber, typeLongInteger,
- &returnType, &returnLong, sizeof(long), &returnSize);
- if (err == noErr)
- err = (OSErr) returnLong;
-
- else {
- //
- // If not, get the icon family and build an icon suite
- //
- err = AEGetParamDesc(&replyEvent, keyDirectObject, typeWildCard, &iconFamily);
- require(err == noErr, AEGetParamDesc);
-
- err = BuildIconSuiteFromAEDesc(true, iconSuite, &iconFamily);
- check(err == noErr);
- }
-
- //
- // Clean up and exit
- //
- (void) AEDisposeDesc(&iconFamily);
-
- AEGetParamDesc:
- (void) AEDisposeDesc(&replyEvent);
-
- SendAppleEvent:
- AEPutParamDesc:
- (void) AEDisposeDesc(&iconPropertySpecifier);
-
- MakePropertySpecifierForSpecifier:
- (void) AEDisposeDesc(&fileSpecifier);
-
- MakeSpecifierForFile:
- (void) AEDisposeDesc(&finderEvent);
-
- MakeAppleEvent:
- HaveScriptableFinder:
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // GetSizeFromIconType
- //----------------------------------------------------------------------------
- Size GetSizeFromIconType(DescType iconType)
- {
- Size size = -1;
-
- switch (iconType) {
- case large8BitData:
- size = kLarge8BitIconSize;
- break;
- case large4BitData:
- size = kLarge4BitIconSize;
- break;
- case large1BitMask:
- size = kLargeIconSize;
- break;
- case small8BitData:
- size = kSmall8BitIconSize;
- break;
- case small4BitData:
- size = kSmall4BitIconSize;
- break;
- case small1BitMask:
- size = kSmallIconSize;
- break;
- }
- return size;
- }
-
-
- //----------------------------------------------------------------------------
- // BuildIconSuiteFromAEDesc
- //
- // OK, this uses the Apple Event Manager to pick the icon data out of the
- // 'ifam' AEDesc.
- //----------------------------------------------------------------------------
- OSErr BuildIconSuiteFromAEDesc(Boolean largeIcons, Handle *iconSuite, AEDesc *iconFam)
- {
- OSErr err;
- Handle suite, icon;
- AERecord rec;
- Ptr buffer;
- DescType large[3] = {large8BitData, large4BitData, large1BitMask};
- DescType small[3] = {small8BitData, small4BitData, small1BitMask};
- DescType *type, iconType, typeCode;
- long count;
- Size maxSize, size, iconSize;
- Boolean maskAdded;
- DescType maskType;
-
- maskAdded = false;
- suite = NULL;
- maxSize = kLarge8BitIconSize;
-
- if (largeIcons == true) {
- type = large;
- maskType = large1BitMask;
- }
- else {
- type = small;
- maskType = small1BitMask;
- }
-
- buffer = NewPtr(maxSize);
- require(buffer != NULL, NewPtr);
-
- err = NewIconSuite(&suite);
- require(err == noErr, NewIconSuite);
-
- err = AECoerceDesc(iconFam, typeAERecord, (AEDesc *) &rec);
- require(err == noErr, AECoerceDesc);
-
- for (count = 0; count < 3; count ++) {
- //
- // loop through the icons and grab the data from the AERecord for
- // each type of icon we're interested in.
- //
- iconType = type[count];
- size = GetSizeFromIconType(iconType);
- err = AEGetKeyPtr(&rec, iconType, iconType, &typeCode,
- buffer, maxSize, &iconSize);
-
- if (err == noErr) {
- //
- // We don't set the error code for this unless the NewHandle
- // call fails, because it's possible that the 'ifam' doesn't
- // have an icon for one that we're interested in.
- //
- icon = NewHandle(size);
-
- if (icon != NULL) {
- //
- // OK, the memory alloc succeeded and we have data. Copy
- // it into the allocated icon and add it to the suite.
- // Set atLeastOne to true, to indicate later that we did
- // in fact add at least one icon to this suite.
- //
- BlockMoveData(buffer, *icon, size);
- err = AddIconToSuite(icon, suite, iconType);
- if ((err == noErr) && (iconType == maskType))
- maskAdded = true;
- }
- else
- err = memFullErr;
- }
- }
-
- (void) AEDisposeDesc(&rec);
-
- AECoerceDesc:
- if ((err != noErr) || (maskAdded == false)) {
- //
- // There was either an error in a memory allocation, or something
- // else went wrong (like no mask was added to the suite). Get
- // rid of the partially created suite.
- //
- DisposeIconSuite(suite, true);
- suite = NULL;
- }
-
- NewIconSuite:
- DisposePtr(buffer);
-
- NewPtr:
- *iconSuite = suite;
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // MakeSpecifierForFile
- //----------------------------------------------------------------------------
- OSErr MakeSpecifierForFile(FSSpecPtr hfsObj, AEDesc *fileSpecifier)
- {
- OSErr err;
- AEDesc nullDesc, hfsData;
- AliasHandle fileAlias;
-
- //
- // Create the file descriptor with the FSSpec passed in.
- //
- err = NewAlias(NULL, hfsObj, &fileAlias);
- require(err == noErr, NewAlias);
-
- HLock((Handle) fileAlias);
- err = AECreateDesc(typeAlias, (Ptr) *fileAlias,
- GetHandleSize((Handle) fileAlias), &hfsData);
- HUnlock((Handle) fileAlias);
- DisposeHandle((Handle) fileAlias);
- require(err == noErr, AECreateDesc);
-
- //
- // Make the object specifier with a null container
- // (i.e., "file of <null>", or just "file")
- //
- nullDesc.descriptorType = typeNull;
- nullDesc.dataHandle = NULL;
- err = CreateObjSpecifier(typeWildCard, &nullDesc,
- formAlias, &hfsData, false, fileSpecifier);
-
- AECreateDesc:
- NewAlias:
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // MakePropertySpecifierForSpecifier
- //----------------------------------------------------------------------------
- OSErr MakePropertySpecifierForSpecifier(DescType property,
- AEDesc *ofSpecifier, AEDesc *propertySpecifier)
- {
- OSErr err;
- AEDesc keyData;
-
- //
- // Create a 'type' AEDesc with the desired property
- //
- err = AECreateDesc(typeType, (Ptr) &property, sizeof(DescType), &keyData);
- require(err == noErr, AECreateDesc);
-
- //
- // With it create a property specifier for the object specifier
- // passed to us.
- //
- err = CreateObjSpecifier(cProperty, ofSpecifier,
- formPropertyID, &keyData, false, propertySpecifier);
-
- (void) AEDisposeDesc(&keyData);
- AECreateDesc:
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // CloneMoveDescList
- //----------------------------------------------------------------------------
- OSErr CloneMoveDescList(AEDescList *objsToMove, FSSpecPtr nuLocation,
- Point globalPt, Boolean replace, Boolean moveFlag)
- {
- OSErr err;
- AppleEvent finderEvent;
- DescType copyMove;
-
- if (moveFlag == true)
- copyMove = kAEMove;
- else
- copyMove = kAEClone;
-
- //
- // Make a Copy/Move Apple event to send to the Finder
- //
- err = MakeAppleEvent(kAECoreSuite, copyMove, &pFinderTarget,
- &finderEvent);
- require(err == noErr, MakeAppleEvent);
-
- //
- // Put the objects to move in the Apple Event as the direct object
- //
- err = AEPutParamDesc(&finderEvent, keyDirectObject, objsToMove);
- require(err == noErr, AEPutParamDesc);
-
- //
- // Put in where the Finder should move the items
- //
- err = AEPutParamPtr(&finderEvent, keyAEInsertHere, typeFSS,
- (Ptr) nuLocation, sizeof(FSSpec));
- require(err == noErr, AEPutParamPtr1);
-
- //
- // Specify whether the Finder should replace any duplicates
- //
- err = AEPutParamPtr(&finderEvent, keyAEReplacing, typeBoolean,
- (Ptr) &replace, sizeof(Boolean));
- require(err == noErr, AEPutParamPtr2);
-
- //
- // And where the Finder should put the items
- //
- err = AEPutParamPtr(&finderEvent, keyGlobalPositionList, typeQDPoint,
- (Ptr) &globalPt, sizeof(Point));
- require(err == noErr, AEPutParamPtr3);
-
- //
- // Send it and return any error
- //
- err = SendAppleEvent(&finderEvent, NULL,
- kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer);
-
- check(err == noErr);
-
- AEPutParamPtr3:
- AEPutParamPtr2:
- AEPutParamPtr1:
- AEPutParamDesc:
- (void) AEDisposeDesc(&finderEvent);
- MakeAppleEvent:
- return err;
- }
-
-
- //-----------------------------------------------------------------------------
- // GetDropFSSpec
- //
- // Given a DragReference, this returns an FSSpec for where the
- // item was dropped. In most cases this is an FSSpec to a directory, but
- // if TrackDrag returns a userCancelledErr, it may have been dropped onto
- // an application.
- //-----------------------------------------------------------------------------
- OSErr GetDropFSSpec(DragReference theDrag, FSSpecPtr dropSpec)
- {
- OSErr err;
- AEDesc theDesc, newDesc;
-
- err = GetDropLocation(theDrag, &theDesc);
- require(err == noErr, GetDropLocation);
-
- err = AECoerceDesc(&theDesc, typeFSS, &newDesc);
- require(err == noErr, AECoerceDesc);
-
- BlockMoveData(*newDesc.dataHandle, dropSpec, sizeof(FSSpec));
-
- (void) AEDisposeDesc(&newDesc);
- AECoerceDesc:
- (void) AEDisposeDesc(&theDesc);
- GetDropLocation:
- return err;
- }
-